﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;

using CommonLib;
using log4net;

namespace RedfinCrawlPro
{

    public class  COMMONCODE
    {
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        // Get File Writer Steam 
        static public StreamWriter OpenFile ( string filenamePrefix )
        {
           StreamWriter fileSW = null;

           // Creating File Name 

            var fileNameSw = new StringWriter();
            fileNameSw.Write("{0}_{1}_{2}_{3}_{4}.csv", filenamePrefix, DateTime.Now.Hour, DateTime.Today.Date.Month, DateTime.Today.Date.Day,
                         DateTime.Today.Date.Year);

            var directorySw = new StringWriter();
            directorySw.Write("\\{0}_{1}\\Day_{2}\\", DateTime.Today.Date.Month,
                         DateTime.Today.Date.Year,DateTime.Today.Day);

            string directory = @"C:\RealEstateReports\" + directorySw.ToString();

            if( !Directory.Exists(directory))
            {
                Directory.CreateDirectory(directory);
            }

            string filename = directory + fileNameSw.ToString();
            log.DebugFormat(" File Name to Write :  {0}",filename);
            
            fileSW = File.CreateText(filename);
            fileSW.WriteLine("MLSID,Type,Price, Beds,Baths,SQFT,Year Built, Address,HOA,PricePerSQFT,ShortSale,URL,FetcherName");
           
            return fileSW;
        }
        static private Dictionary<string, string> mlsDictionary = new Dictionary<string, string>();

        public static void PrintRecord(StreamWriter fileSW, RefinPropertyData item, string fetcherName,double pricePerSqft,bool addtoDictionary=true)
        {
            string url = "http://redfin.com" + item.URL;

            string tmpStr = string.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12}", item.mlsid, item.type, item.price,
                            item.beds, item.baths, item.sqft, item.year_built,
                            item.address_data.ToString(), item.hoa_dues, pricePerSqft, item.is_short_sale, url, fetcherName);
            

            log.Debug(tmpStr);
            fileSW.WriteLine(tmpStr);

            if (!addtoDictionary) return;

            // Thread Safe 
            lock (mlsDictionary)
            {
                if (mlsDictionary.ContainsKey(item.mlsid))
                {
                    mlsDictionary.Remove(item.mlsid);
                    //mlsDictionary[item.mlsid] = tmpStr;
                }

                mlsDictionary[item.mlsid] = tmpStr;
                
            }
        }

        public static bool PerformBasicChks(RefinPropertyData item)
        {
            bool returnVal = true;

            if ((item == null) || (item.isSold) || (item.price <= 0) || (item.mlsid == null) || (item.mls_status == -1) || ( item.sqft <=0 ) )
            {
                returnVal = false;
            }

            return returnVal;
        }

        private static bool reportDone = false;
        public static void WriteUpFinalReport()
        {
            if (reportDone) return;
            StreamWriter fileSW = COMMONCODE.OpenFile("Report_Summary_");

            lock (mlsDictionary)
            {
                foreach (KeyValuePair<string, string> item in mlsDictionary)
                {                    
                    fileSW.WriteLine(item.Value);
                }
                fileSW.Close();
                reportDone = true;
            }

        }
    }

    public class BestofAllProcessor : ProcessInterface
    {
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        public bool processrawData(string fetcherName, object rawDatatoProcess, ProcessorConfigBaseRec processorConfigObject)
        {
            log.DebugFormat(" BestofAllProcessor :  Processing Data Happily:-) ");
            StreamWriter fileSW = COMMONCODE.OpenFile("Best_" + fetcherName);
            if (fileSW == null)
            {
                log.FatalFormat(" Unable to Open File ");
                return false;
            }
            var datatoProcess = rawDatatoProcess as RawCrawledData;
            if (datatoProcess == null)
            {
                log.WarnFormat(" Unable to Process Data due to  Data Pointer being NULL");
                return false;
            }

            // Process Data 

            foreach (var item in datatoProcess.RedFinProperyList)
            {
                if (!COMMONCODE.PerformBasicChks(item))
                {
                    continue;
                }

                double pricePerSq = item.price / item.sqft;

                if ((DateTime.Today.Year - 15 <= item.year_built) && pricePerSq <= 180 && item.hoa_dues <= 200 )
                {
                COMMONCODE.PrintRecord(fileSW, item, fetcherName, pricePerSq);                   
                }
            }

            fileSW.Close();
            return true;
        }

        //Read processor specific configuration.. 
        public ProcessorConfigBaseRec getConfiguration(XmlNode processorNode)
        {
            return null;
        }



    }


    public class BetterofAllProcessor : ProcessInterface
    {
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        public bool processrawData(string fetcherName, object rawDatatoProcess, ProcessorConfigBaseRec processorConfigObject)
        {
            log.DebugFormat(" Better Processor  :  Processing Data Happily:-) ");
            StreamWriter fileSW = COMMONCODE.OpenFile("Better_" + fetcherName);
            if (fileSW == null)
            {
                log.FatalFormat(" Unable to Open File ");
                return false;
            }
            var datatoProcess = rawDatatoProcess as RawCrawledData;
            if (datatoProcess == null)
            {
                log.WarnFormat(" Unable to Process Data due to  Data Pointer being NULL");
                return false;
            }

            // Process Data 


            foreach (var item in datatoProcess.RedFinProperyList)
            {
                if (!COMMONCODE.PerformBasicChks(item))
                {
                    continue;
                }

                double pricePerSQ = item.price / item.sqft;

                if ((DateTime.Today.Year - 20 <= item.year_built) && pricePerSQ <= 200 && item.hoa_dues <= 250)
                {
                COMMONCODE.PrintRecord(fileSW, item, fetcherName, pricePerSQ);
                }
            }

            fileSW.Close();
            return true;
        }
        //Read processor specific configuration.. 
        public ProcessorConfigBaseRec getConfiguration(XmlNode processorNode)
        {
            return null;
        }
    }


    public class RawDataoffAllProcessor : ProcessInterface
    {
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        public bool processrawData(string fetcherName, object rawDatatoProcess, ProcessorConfigBaseRec processorConfigObject)
        {
            log.DebugFormat(" Better Processor  :  Processing Data Happily:-) ");
            StreamWriter fileSW = COMMONCODE.OpenFile("Rawdata_" + fetcherName);
            if (fileSW == null)
            {
                log.FatalFormat(" Unable to Open File ");
                return false;
            }
            var datatoProcess = rawDatatoProcess as RawCrawledData;
            if (datatoProcess == null)
            {
                log.WarnFormat(" Unable to Process Data due to  Data Pointer being NULL");
                return false;
            }

            // Process Data 


            foreach (var item in datatoProcess.RedFinProperyList)
            {
                if (!COMMONCODE.PerformBasicChks(item))
                {
                    continue;
                }

                double pricePerSQ = item.price / item.sqft;

                //if ((DateTime.Today.Year - 20 <= item.year_built) && pricePerSQ <= 200 && item.hoa_dues <= 250)
                {
                    COMMONCODE.PrintRecord(fileSW, item, fetcherName, pricePerSQ,false);
                }
            }

            fileSW.Close();
            return true;
        }

        //Read processor specific configuration.. 
        public ProcessorConfigBaseRec getConfiguration(XmlNode processorNode)
        {
            return null;
        }
    }


    public class ReportRealEstate:ReportSummaryIntf
    {

        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        public bool reportSummary()
        {
            log.DebugFormat("Starting Up Reporting Summary $$$$$$$$$$$$$$$");
            COMMONCODE.WriteUpFinalReport();
            log.DebugFormat("Completed  Reporting Summary $$$$$$$$$$$$$$$");
            return true;
        }

    }

}
